package com.yuantu.judiciary.controller;

import com.yuantu.judiciary.annotation.Log;
import com.yuantu.judiciary.common.Response;
import com.yuantu.judiciary.common.ResponseFactory;
import com.yuantu.judiciary.constant.SystemTypeConstant;
import com.yuantu.judiciary.dao.IOrganizationDao;
import com.yuantu.judiciary.model.dto.AccountInfoDTO;
import com.yuantu.judiciary.model.enums.AccountState;
import com.yuantu.judiciary.model.enums.AuthState;
import com.yuantu.judiciary.model.enums.EndpointType;
import com.yuantu.judiciary.model.form.*;
import com.yuantu.judiciary.model.vo.*;
import com.yuantu.judiciary.service.IMinHangApiService;
import com.yuantu.judiciary.service.IUserService;
import com.yuantu.judiciary.utils.JwtUtil;
import com.yuantu.judiciary.utils.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotEmpty;
import java.util.Collections;
import java.util.List;

/**
 * 系统用户模块
 *
 * @author syw
 * @since 2023-08-03
 **/
@RestController
@RequestMapping("/user")
@Api(tags = "系统用户模块")
@Slf4j
@RequiredArgsConstructor
public class SysUserController extends BaseController {

    private final IUserService userService;
    private final IMinHangApiService minHangApiService;
    private final IOrganizationDao organizationDao;

    @Value("${spring.profiles.active}")
    private String active;

    @ApiOperation(value = "app-登录")
    @PostMapping("/login/app")
    public Response<TokenVO> loginApp(@RequestBody @Validated LoginAppForm form) {
        AccountInfoDTO user = userService.getUserAccountInfoByApp(form);
        user.setEndpoint(EndpointType.APP);
        TokenVO token = JwtUtil.generateTokens(user);
        String key = EndpointType.APP.name() + "_" + user.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    @ApiOperation(value = "网页端-登录")
    @PostMapping("/login/web")
    public Response<TokenVO> loginWeb(@RequestBody @Validated LoginAppForm form) {
        AccountInfoDTO user = userService.getUserAccountInfoByWeb(form);
        user.setEndpoint(EndpointType.WEB);
        TokenVO token = JwtUtil.generateTokens(user);
        String key = EndpointType.WEB.name() + "_" + user.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    @Log(title = "登录")
    @ApiOperation(value = "管理端-登录")
    @PostMapping("/login")
    public Response<TokenVO> login(@RequestBody @Validated LoginForm form) {
        AccountInfoDTO user = userService.getUserAccountInfo(form);
        user.setEndpoint(EndpointType.PLATFORM);
        TokenVO token = JwtUtil.generateTokens(user);
        String key = EndpointType.PLATFORM.name() + "_" + user.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    @ApiOperation(value = "一体机-登录")
    @PostMapping("/login/machine")
    public Response<TokenVO> loginMachine(@RequestBody @Validated LoginMachineForm form) {
        AccountInfoDTO user = userService.getUserAccountInfoByMachine(form);
        user.setEndpoint(EndpointType.ALIPAY_APPLET);
        TokenVO token = JwtUtil.generateTokens(user);
        String key = EndpointType.ALIPAY_APPLET.name() + "_" + user.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    @ApiOperation(value = "微信小程序-登录")
    @PostMapping("/login/applet")
    public Response<TokenVO> loginApplet(@RequestBody LoginAppletForm form) {
        AccountInfoDTO user = userService.getUserAccountInfoByApplet(form);
        user.setEndpoint(EndpointType.APPLET);
        TokenVO token = JwtUtil.generateTokens(user);
        String key = EndpointType.APPLET.name() + "_" + user.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    @ApiOperation(value = "微信小程序-获取手机号")
    @GetMapping("/get/phone")
    public Response<String> getPhoneNumber(@RequestParam String phoneCode) {
        String phoneNumber = userService.getPhoneInfo(phoneCode);
        return ResponseFactory.okResponse(phoneNumber);
    }

    @ApiOperation(value = "微信小程序-登录")
    @GetMapping("/login/test")
    public Response<TokenVO> loginTest(@RequestParam Long accountId) {
//        AccountInfoDTO user = new AccountInfoDTO();
//        user.setUsername("陆韬");
//        user.setUserId(5L);
//        user.setAccountId(4821L);
//        user.setOrganizationId(4302L);
//        user.setEndpoint(EndpointType.APPLET);
        AccountInfoDTO userInfo = userService.getAccountInfoByAccountId(accountId);
        userInfo.setEndpoint(EndpointType.APPLET);
        TokenVO token = JwtUtil.generateTokens(userInfo);
        String key = EndpointType.APPLET.name() + "_" + userInfo.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    @ApiOperation(value = "支付宝小程序-登录")
    @PostMapping("/login/applet/ali")
    public Response<TokenVO> loginAliApplet(@RequestBody @Validated LoginAliAppletForm form) {
        AccountInfoDTO user = userService.getUserAccountInfoByAliApplet(form);
        user.setEndpoint(EndpointType.ALIPAY_APPLET);
        TokenVO token = JwtUtil.generateTokens(user);
        String key = EndpointType.ALIPAY_APPLET.name() + "_" + user.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    @ApiOperation(value = "支付宝小程序-登录（获取身份信息）")
    @PostMapping("/login/applet/ali/without-verify")
    public Response<TokenVO> loginAliAppletWithoutVerify(@RequestBody @Validated LoginAliAppletWithoutVerifyForm form) {
        AccountInfoDTO user = userService.getUserAccountInfoByAliAppletWithoutVerify(form);
        user.setEndpoint(EndpointType.ALIPAY_APPLET);
        TokenVO token = JwtUtil.generateTokens(user);
        String key = EndpointType.ALIPAY_APPLET.name() + "_" + user.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    @Log(title = "新增用户")
    @ApiOperation(value = "管理端-新增用户")
    @PostMapping("/add")
    public Response<Boolean> add(@RequestBody @Validated LoginForm form) {
        return ResponseFactory.okResponse(userService.add(form));
    }

    @Log(title = "更新用户")
    @ApiOperation(value = "管理端-更新用户")
    @PostMapping("/modify")
    public Response<Boolean> modify(@RequestBody @Validated ModifySysUserInfoForm form) {
        return ResponseFactory.okResponse(userService.modify(form));
    }

    @Log(title = "删除用户")
    @ApiOperation(value = "管理端-删除用户")
    @PostMapping("/delete")
    public Response<Boolean> delete(@RequestBody @NotEmpty List<Long> id) {
        Long accountId = getLoginAccount().getAccountId();
        return ResponseFactory.okResponse(userService.delete(accountId, id));
    }

    @ApiOperation(value = "管理端-用户列表")
    @PostMapping("/list")
    public Response<PageVO<SysUserInfoVO>> list(@PageableDefault(sort = "createTime", direction = Sort.Direction.DESC) Pageable pageable,
                                                @RequestBody GetSysUserInfoForm form) {
        return ResponseFactory.okResponse(userService.list(form, pageable));
    }

    @ApiOperation(value = "注册组织信息")
    @PostMapping("/register/org")
    public Response<Boolean> registerOrg(@RequestBody @Validated RegisterForm form,
                                         @RequestHeader("System-Type") String systemType) {
        Long accountId = getLoginAccount().getAccountId();
        if (!verifyPersonInfo(form, systemType)) {
            return ResponseFactory.errResponse("姓名和身份证号有误");
        }
        form.setTwoFactorAuthState(true);
        return ResponseFactory.okResponse(userService.registerOrg(accountId, form));
    }

    @ApiOperation(value = "注册并绑定邀请码")
    @PostMapping("/register/bind")
    public Response<String> registerBind(@RequestBody @Validated RegisterBindForm form) {
        return ResponseFactory.okResponse(userService.registerBind(form));
    }

    @ApiOperation(value = "注册绑定分享信息")
    @PostMapping("/register/bind/share")
    public Response<TokenVO> registerBindShare(@RequestBody @Validated RegisterBindShareForm form) {
        return ResponseFactory.okResponse(userService.registerBindShare(form));
    }

    @ApiOperation(value = "更新组织信息")
    @PostMapping("/modify/org")
    public Response<Boolean> modifyOrg(@RequestBody @Validated RegisterForm form) {
        Long accountId = getLoginAccount().getAccountId();
        return ResponseFactory.okResponse(userService.modifyOrg(accountId, form));
    }

    @ApiOperation(value = "根据信用代码查询企业信息")
    @GetMapping("/query/org/credit")
    public Response<OrgSimpleVO> findOrgInfoByCreditCode(@RequestParam String creditCode) {
        return ResponseFactory.okResponse(userService.findOrgInfoByCreditCode(creditCode));
    }

    @ApiOperation(value = "获取组织信息")
    @GetMapping("/get/org")
    public Response<RegisterForm> getOrg() {
        Long accountId = getLoginAccount().getAccountId();
        return ResponseFactory.okResponse(userService.getOrg(accountId));
    }

    @ApiOperation(value = "获取用户信息")
    @PostMapping("/get")
    public Response<UserInfoVO> getUserInfo() {
        Long accountId = getLoginAccount().getAccountId();
        return ResponseFactory.okResponse(userService.getUserInfo(accountId));
    }

    @ApiOperation(value = "切换账号")
    @PostMapping("/exchange")
    public Response<TokenVO> exchange(@RequestBody @Validated ExchangeAccountForm form) {
        AccountInfoDTO user = userService.exchange(form.getAccountId());
        user.setEndpoint(form.getEndpoint());
        TokenVO token = JwtUtil.generateTokens(user);
        String key = form.getEndpoint().name() + "_" + user.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    // todo 切换账号时查看账号列表
    @ApiOperation(value = "账号列表")
    @GetMapping("/list/org")
    public Response<List<AccountInfoVO>> listOrg() {
        Long accountId = getLoginAccount().getAccountId();
        return ResponseFactory.okResponse(userService.listOrg(accountId));
    }

    @ApiOperation(value = "检查账号状态")
    @GetMapping("/verify")
    public Response<String> verifyAccount() {
        Long userId = getLoginAccount().getAccountId();
        String res = userService.verifyAccount(userId);
        return ResponseFactory.okResponse(res);
    }

    @ApiOperation(value = "管理端-运营商查询")
    @PostMapping("/search/operator")
    public Response<List<AccountInfoVO>> searchAccount(@RequestBody SearchAccountForm form) {
        return ResponseFactory.okResponse(userService.searchAccount(form));
    }

    @ApiOperation(value = "管理端-套餐用户查询")
    @PostMapping("/search/vip-org")
    public Response<List<AccountInfoVO>> searchOrgAccount(@RequestBody SearchAccountForm form) {
        return ResponseFactory.okResponse(userService.searchOrgAccount(form));
    }

    @ApiOperation(value = "app-注销")
    @PostMapping("/cancel")
    public Response<Boolean> cancel() {
        Long accountId = getLoginAccount().getAccountId();
        return ResponseFactory.okResponse(userService.delete(accountId, Collections.singletonList(accountId)));
    }

    @ApiOperation(value = "更新账号信息")
    @PostMapping("/modify/account")
    public Response<Boolean> modifyAccount(@RequestBody @Validated ModifyAccountForm form) {
        Long accountId = getLoginAccount().getAccountId();
        return ResponseFactory.okResponse(userService.modifyAccount(accountId, form));
    }

    @ApiOperation(value = "查询支付宝有关用户信息")
    @PostMapping("/query/ali/user")
    public Response<List<AccountInfoVO>> queryAliUserInfos(@RequestParam String userName) {
        return ResponseFactory.okResponse(userService.queryAliUserInfos(userName));
    }

    @ApiOperation(value = "查询用户是否黑名单中")
    @GetMapping("/is/black")
    public Response<BlackInfoVO> queryUserIsBlack(@RequestParam String idNumber) {
        if(StringUtil.isEmpty(idNumber)){
            return ResponseFactory.errResponse(
                    "未完成实名认证,请使用【查个人】功能进行查询。");
        }
        return ResponseFactory.okResponse(userService.queryUserIsBlack(idNumber));
    }

    @ApiOperation(value = "查询用户是否可以分享")
    @GetMapping("/is/share")
    public Response<Boolean> isShare() {
        Long accountId = getLoginAccount().getAccountId();
        return ResponseFactory.okResponse(userService.isShare(accountId));
    }

    @ApiOperation(value = "根据accountId获取token信息")
    @PostMapping("/get/token")
    public Response<TokenVO> getToken(@RequestBody @Validated ExchangeAccountForm form) {
        AccountInfoDTO user = userService.exchange(form.getAccountId());
        user.setEndpoint(form.getEndpoint());
        TokenVO token = JwtUtil.generateTokens(user);
        String key = form.getEndpoint().name() + "_" + user.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    @ApiOperation(value = "查询用户是否可以查看分配使用次数情况 true 是 false 否")
    @GetMapping("/is/divide")
    public Response<Boolean> isDivide() {
        Long accountId = getLoginAccount().getAccountId();
        return ResponseFactory.okResponse(userService.isDivide(accountId));
    }

    @ApiOperation(value = "获取企业有关信息 web端")
    @GetMapping("/org/info")
    public Response<EnterSimpleInfoVO> getEnterInfo(@RequestParam Long orgId) {
        return ResponseFactory.okResponse(userService.getEnterInfo(orgId));
    }

    @ApiOperation(value = "修改企业有关信息 web端")
    @PostMapping("/update/org/info")
    public Response<Boolean> updateEnterInfo(@RequestBody EnterSimpleInfoVO enterSimpleInfo) {
        return ResponseFactory.okResponse(userService.updateEnterInfo(enterSimpleInfo));
    }

    @ApiOperation(value = "注册用户 web端")
    @PostMapping("/register/web")
    public Response<TokenVO> registerOrgUser(@Validated @RequestBody AccountWebRegisterVO webRegister) {
        AccountInfoDTO accountInfo = userService.registerOrgUser(webRegister);
        accountInfo.setEndpoint(EndpointType.WEB);
        TokenVO token = JwtUtil.generateTokens(accountInfo);
        String key = EndpointType.WEB.name() + "_" + accountInfo.getAccountId().toString();
        JwtUtil.revokeUserToken(key);
        JwtUtil.saveToken(key, token.getAccessToken());
        return ResponseFactory.okResponse(token);
    }

    //认证个人信息二要素
    private boolean verifyPersonInfo(RegisterForm form, String systemType) {
        //测试环境直接通过，省去加白名单的烦恼。
        if (StringUtils.equals("dev", active)) {
            return true;
        }
        //检查账户信息是否已经认证并通过。
        boolean verifyName = organizationDao.countDistinctByUsernameAndIdNumberAndAuthStateAndDeletedFalse(
                form.getUsername(), form.getIdNumber(), AuthState.PASS) > 0;
        if (verifyName) return true;
        if (StringUtil.isEmpty(systemType) || SystemTypeConstant.WX_XCX.equals(systemType)) {
            return minHangApiService.idNumberVerify(form.getEnterName(), form.getIdNumber());
        }
        return true;
    }

}


